﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Web.Http;
using System.Xml;
using System.Xml.Serialization;
using Ttifa.Infrastructure;
using Ttifa.Infrastructure.Extensions;
using Ttifa.Infrastructure.Utils;
using Ttifa.Log;
using Ttifa.WebApiBase;
using Ttifa.WebApiBase.Filters;

namespace Ttifa.WebApi.Controllers
{
    public class JZBController : ApiController
    {
        private string CreateXml()
        {
            XmlDocument xmlDoc = new XmlDocument();
            //加入XML的声明段落
            xmlDoc.CreateXmlDeclaration("1.0", "GBK", "yes");
            //var xmlnode = xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
            //xmlDoc.AppendChild(xmlnode);

            //根元素
            var xmlRoot = xmlDoc.CreateElement("Result");
            //xmlDoc.AppendChild(xmlRoot);

            //加入另一个元素
            var xmlelem2 = xmlDoc.CreateElement("Name");
            var xmltext = xmlDoc.CreateTextNode("The text of the sample element");
            xmlelem2.AppendChild(xmltext);

            //附加子节点
            xmlRoot.AppendChild(xmlelem2);
            //附加根节点
            xmlDoc.AppendChild(xmlRoot);

            var xmlString = string.Empty;
            MemoryStream ms = new MemoryStream();
            XmlTextWriter writer = new XmlTextWriter(ms, Encoding.GetEncoding("GBK"));
            writer.Formatting = Formatting.Indented;
            xmlDoc.Save(writer);
            ms.Position = 0;
            using (StreamReader sr = new StreamReader(ms, Encoding.GetEncoding("GBK")))
            {
                xmlString = sr.ReadToEnd();
            }

            return xmlString;
        }

        private string XmlSerialize<T>(T obj, string rootName = "")
        {
            var xmlString = string.Empty;
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer xmlser = string.IsNullOrEmpty(rootName) ? new XmlSerializer(typeof(T)) :
                    new XmlSerializer(typeof(T), new XmlRootAttribute(rootName));
                xmlser.Serialize(ms, obj);

                ms.Position = 0;
                StreamReader sr = new StreamReader(ms);
                xmlString = sr.ReadToEnd();
            }

            return xmlString;
        }

        #region 见证宝通讯
        /// <summary>
        /// 请求见证宝
        /// </summary>
        /// <param name="service">服务</param>
        /// <param name="param">请求参数</param>
        /// <param name="orderNo">请求流水号</param>
        /// <returns></returns>
        public ApiResult Post(JZBServices service, Dictionary<string, string> param, string orderNo = "")
        {
            var customerCode = ConfigManager.GetSetting("JZBCustomerCode");
            var paramString = BusinessParam(param);
            var paramByteSize = paramString.ByteCount();
            if (string.IsNullOrEmpty(orderNo))
                orderNo = CodeHelper.OrderNo();
            else if (orderNo.Length > 20)
                return new ApiResult(ApiStatus.Fail, "流水号长度超过20位");
            orderNo = orderNo.PadRight(20);

            string businessHead = BusinessHead(customerCode, service, orderNo, paramByteSize);
            var businessHeadByteSize = businessHead.ByteCount();
            if (businessHeadByteSize != 122)
            {
                LogFactory.GetLogger().AddProperty("ApiResult", $"业务头长度错误:{businessHeadByteSize}").Info(service.ToString().Substring(1));
                return new ApiResult(ApiStatus.Fail, "业务头长度错误", businessHeadByteSize);
            }

            var head = CommunicationHead(customerCode, orderNo, businessHeadByteSize + paramByteSize);
            if (head.ByteCount() != 222)
            {
                LogFactory.GetLogger().AddProperty("ApiResult", $"通讯报文头长度错误:{head.ByteCount()}").Info(service.ToString().Substring(1));
                return new ApiResult(ApiStatus.Fail, "通讯报文头长度错误", head.ByteCount());
            }

            var content = new StringBuilder();
            content.Append(head);
            content.Append(businessHead);
            content.Append(paramString);
            string resp = CommunicationHelper.Http(ConfigManager.GetSetting("JZBB2BiCService"), content.ToString());

            JZBMessage jzbMsg = JZBMessage.ParseResponse(resp);
            var rspCode = jzbMsg.BusinessHead.ByteSubstring(36, 6);
            var rspMsg = jzbMsg.CommunicationHead.ByteSubstring(93, 100).Trim();
            var apistatus = ApiStatus.OK;
            if (rspMsg != "000000")
            {
                apistatus = rspCode.ToLower() == "err020" ? ApiStatus.TradeFail : ApiStatus.Fail;
                rspMsg = $"{rspCode}:{rspMsg}";
            }

            var result = new ApiResult(apistatus, rspMsg, jzbMsg.Content);

            return result;
        }

        /// <summary>
        /// 通讯报文头(222字节)
        /// </summary>
        /// <param name="contentSize"></param>
        /// <returns></returns>
        private string CommunicationHead(string customerCode, string orderNo, int contentSize)
        {
            var tradeCode = ConfigManager.GetSetting("JZBTradeCode");
            var systemCode = ConfigManager.GetSetting("JZBSystemCode");
            var text = new StringBuilder();
            text.Append("A001");//报文版本
            text.Append(systemCode);//银行目标系统
            text.Append("01");//报文编码 gbk
            text.Append("01");//通讯协议 01 tcpip 02 http
            text.Append(customerCode.BytePadRight(20));//外联客户代码 长度20
            text.Append(contentSize.ToString().BytePadLeft(10, '0'));//报文字节长度 长度10
            text.Append(tradeCode);//交易码
            text.Append("00000");//操作员
            text.Append("01");//服务类型：01请求，02应答
            text.Append(DateTime.Now.ToString("yyyyMMddHHmmss"));//日期+时间
            text.Append(orderNo);//订单号 长度20
            text.Append("000000");//返回码
            text.Append(":success".PadRight(100));//返回描述
            text.Append("0");//后续包标志
            text.Append("000");//请求次数
            text.Append("0");//签名标识
            text.Append("1");//签名数据包格式：0裸签 1 PKCS7
            text.Append("RSA-SHA1".PadRight(12));//签名算法
            text.Append("0".PadLeft(10, '0'));//签名数据长度
            text.Append("0");//附件数量

            return text.ToString();
        }

        /// <summary>
        /// 业务报文 （122字节）
        /// </summary>
        /// <param name="service"></param>
        /// <returns></returns>
        private string BusinessHead(string customerCode, JZBServices service, string orderNo, int contentSize)
        {
            var text = new StringBuilder();
            text.Append(service.ToString().Substring(1));//接口
            text.Append("01");//服务类型 01 请求 02 应答
            text.Append("".PadRight(16));//mac码
            text.Append(DateTime.Now.ToString("yyyyMMddHHmmss"));//日期+时间
            text.Append("000000");//应答码 000000成功
            text.Append("success".BytePadRight(42));//应答描述
            text.Append("0");//后续包标识
            text.Append(contentSize.ToString().PadLeft(8, '0'));//报文体长度
            text.Append("00000");//操作员
            text.Append(orderNo);//流水号
            text.Append(customerCode);//企业代码(4)，由银行指定，同通讯报文头的外联客户代码

            return text.ToString();
        }

        /// <summary>
        /// 拼接接口参数（&）
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private string BusinessParam(Dictionary<string, string> param)
        {
            var text = new StringBuilder();
            foreach (var field in param)
            {
                text.Append(field.Value + "&");
            }

            return text.ToString();
        }
        #endregion
    }
}
